package com.mytomcat.catalina.net;

import com.mytomcat.catalina.handler.ConnectionHandler;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Nio的endpoint类
 *
 * @author supu
 * @date 2019-04-22 13:41
 **/
public class NioEndpoint extends AbstractEndpoint {
    private static final Logger LOGGER = LoggerFactory.getLogger(NioEndpoint.class);

    private static AtomicInteger socketCount = new AtomicInteger(0);

    private static Executor executor;

    private static ServerSocket serverSocket;

    private final SynchronizedQueue<Socket> socketQueue = new SynchronizedQueue<>();

    @Override
    public void start() {
        // 初始化Socket连接和创建线程池
        init();

        // 开启接收请求器
        startAcceptorThread();

        // 开启轮询器
        startPollerThread();
    }

    private void init(){
        try {
            // init socket监听
            serverSocket = new ServerSocket(getPort());
            LOGGER.info("mytomcat start success");
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 创建线程池
        executor = getExecutor();
        if(executor == null){
            createExecutor();
            executor = getExecutor();
        }
    }

    class Poller implements Runnable {
        @Override
        public void run() {
            while (true) {
                Socket socket = socketQueue.poll();
                if(socket != null){
                    LOGGER.info("{}-{} 次处理socket连接", Thread.currentThread().getName(), socketCount);
                    executor.execute(new ConnectionHandler(socket, getConnector()));
                }
            }
        }
    }

    class Acceptor implements Runnable {
        @Override
        public void run() {
            while (true) {
                try {
                    Socket socket = null;
                    while ((socket = serverSocket.accept()) != null) {
                        // 等待网络请求到来
                        LOGGER.info("{}-{} 次请求连接socket", Thread.currentThread().getName(), socketCount.incrementAndGet());

                        // 将socket放入队列中
                        socketQueue.offer(socket);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void startAcceptorThread(){
        Acceptor acceptor = new Acceptor();
        Thread acceptorThread = new Thread(acceptor, "ClientAcceptor");
        acceptorThread.setPriority(Thread.NORM_PRIORITY);
        acceptorThread.start();
    }

    private void startPollerThread(){
        Poller poller = new Poller();
        Thread pollerThread = new Thread(poller, "ClientPoller");
        pollerThread.setPriority(Thread.NORM_PRIORITY);
        pollerThread.start();
    }
}
